import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import * as bcrypt from 'bcrypt';
import { v7 as uuidV7 } from 'uuid';
import { ClientInfoDto, LoginDto, RegisterDto } from './dto';
import { UserEntity } from './entities/user.entity';
import { ResultData } from 'src/common/utils/result';
import { CacheEnum, DelFlagEnum, StatusEnum } from 'src/common/enum';
import { RedisService } from 'src/common/redis/redis.service';
import { JwtService } from '@nestjs/jwt';
import { LOGIN_TOKEN_EXPIRESIN } from 'src/common/constant';
import { LoginLogEntity } from './entities/loginLog.entity';

@Injectable()
export class UserService {
  constructor(
    @InjectRepository(UserEntity)
    private readonly userRepo: Repository<UserEntity>,
    @InjectRepository(LoginLogEntity)
    private readonly logRepo: Repository<LoginLogEntity>,
    private readonly jwtService: JwtService,
    private readonly redisService: RedisService,
  ) {}
  async login(form: LoginDto, clientInfo: ClientInfoDto) {
    const userData = await this.userRepo.findOne({
      where: {
        userName: form.username,
        isDelete: DelFlagEnum.NORMAL,
      },
      select: ['id', 'password', 'status', 'isDelete', 'nickName', 'userName'],
    });
    if (!userData) {
      return Promise.reject('用户不存在');
    }
    if (userData.isDelete === DelFlagEnum.DELETE || userData.status === StatusEnum.STOP) {
      return Promise.reject('当前账户不可用，请联系管理员');
    }
    if (!bcrypt.compareSync(form.password, userData.password)) {
      return Promise.reject('帐号或密码错误');
    }
    const uuid = uuidV7();
    const accessToken = this.jwtService.sign({ uuid, userId: userData.id });
    const metaData = {
      browser: clientInfo.browser,
      ipaddr: clientInfo.ipaddr,
      os: clientInfo.os,
      token: uuid,
      user: userData,
      userId: userData.id,
      username: userData.userName,
      nickName: userData.nickName,
    };
    await this.logRepo.insert({
      userName: userData.userName,
      userId: userData.id,
      ipaddr: clientInfo.ipaddr,
      location: '',
      userAgent: clientInfo.userAgent,
      browser: clientInfo.browser,
      os: clientInfo.os,
      type: '0',
    });
    await this.redisService.set(
      `${CacheEnum.LOGIN_TOKEN_KEY}${uuid}`,
      metaData,
      LOGIN_TOKEN_EXPIRESIN,
    );
    return ResultData.ok(accessToken, '登录成功');
  }

  async register(form: RegisterDto, clientInfo: ClientInfoDto) {
    const userData = await this.userRepo.findOne({
      where: {
        userName: form.username,
      },
      select: ['id', 'nickName', 'userName'],
    });
    if (userData) {
      return Promise.reject('用户已存在');
    }
    const salt = bcrypt.genSaltSync(10);
    if (form.password) {
      form.password = bcrypt.hashSync(form.password, salt);
    }
    await this.userRepo.insert({
      password: form.password,
      userName: form.username,
      nickName: form.username,
    });
    await this.logRepo.insert({
      userName: userData.userName,
      userId: userData.id,
      ipaddr: clientInfo.ipaddr,
      location: '',
      userAgent: clientInfo.userAgent,
      browser: clientInfo.browser,
      os: clientInfo.os,
      type: '1',
    });
    return ResultData.ok(null, '注册成功');
  }
}
